﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.WindowsAzure;
using System.Configuration;
using AzureGames.Data.Implementation;
using System.IO;
using Microsoft.WindowsAzure.StorageClient;

using InMemory = AzureGames.Data.InMemory;
using Implementation = AzureGames.Data.Implementation;

namespace AzureGames.Data.Utility
{

    public class RepositoryController
    {
        private IGameDefinitionRepository SourceGameDefinitionRepository { get; set; }
        private IUserRepository SourceUserRepository { get; set; }
        private IAIPlayerRepository SourceAIPlayerRepository { get; set; }
        public IResourceRepository SourceResourceRepository { get; set; }
        
        private IGameDefinitionRepository TargeGameDefinitionRepository { get; set; }
        private IUserRepository TargetUserRepository { get; set; }
        private IAIPlayerRepository TargetAIPlayerRepository { get; set; }
        public IResourceRepository TargetResourceRepository { get; set; }

        public RepositoryController()
        {
            CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
            {
                // Provide the configSetter with the initial value
                configSetter(ConfigurationManager.AppSettings[configName]);
            });

            this.SourceGameDefinitionRepository = new InMemory.GameDefinitionRepository();
            this.SourceUserRepository = new InMemory.UserRepository();
            this.SourceAIPlayerRepository = new InMemory.PlayerRepository();
            this.SourceResourceRepository = new InMemory.ResourceRepository();

            this.TargetUserRepository = new Implementation.UserRepository();
            this.TargeGameDefinitionRepository = new Implementation.GameDefinitionRepository();
            this.TargetAIPlayerRepository = new Implementation.AIPlayerRepository();
            this.TargetResourceRepository = new Implementation.ResourceRepository();

        }

        public void AddGameDefinitions()
        {
            foreach (var gameDef in SourceGameDefinitionRepository.GetGameDefinitions())
            {
                AddGameDefinition(gameDef);
                AddResources(gameDef.CSSFiles);
                AddResources(gameDef.JavascriptFiles);
                AddResources(gameDef.Media);                
                AddAIPlayers(gameDef.ID);
                AddResources(new List<Guid>{gameDef.GameImage});
            }
        }

        private void AddResources(List<Guid> resourceIds)
        {
            foreach(var resourceId in resourceIds)
            {
                var source = SourceResourceRepository.GetResource(resourceId);
                TargetResourceRepository.UpdateResource(source);
            }   
        }      

        private void AddAIPlayers(int gameId)
        {
            var targetPlayers = TargetAIPlayerRepository.GetAIPlayers(gameId);

            foreach (var player in SourceAIPlayerRepository.GetAIPlayers(gameId))
            {
                var target = targetPlayers.FirstOrDefault(p => p.ID == player.ID);

                if (target == null)
                    TargetAIPlayerRepository.AddAIPlayer(player);
                else
                {
                    if (target.LastUpdatedDate < player.LastUpdatedDate)
                        TargetAIPlayerRepository.UpdateAIPlayer(player);
                }

                AddResources(new List<Guid> { player.ResourceID });
            }
        }

        public void AddUsers()
        {
            foreach (var user in SourceUserRepository.GetUsers())
            {
                AddUser(user);
            }
        }

        private void AddUser(Model.User user)
        {
            var target = TargetUserRepository.GetUser(user.ID);

            if (target == null)
                TargetUserRepository.AddUser(user);
            else
            {
                if (target.LastUpdatedDate < user.LastUpdatedDate)
                    TargetUserRepository.UpdateUser(user);
            }

        }        

        private void AddGameDefinition(Model.GameDefinition def)
        {

            var target = TargeGameDefinitionRepository.GetGameDefinition(def.ID);

            if (target == null)
            {                
                TargeGameDefinitionRepository.AddGameDefinition(def);
            }
            else
            {
                if (target.LastUpdatedDate < def.LastUpdatedDate)
                    TargeGameDefinitionRepository.UpdateGameDefinition(def);
            }
        }
    }
}
